/*
 * UserManager.java
 */

package superConference;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

/**
 * The UserManager class is used to load the users from an external file and 
 * supply the information to other classes.
 * @author Oscar Hong
 * @version 12/1/2013
 */
public class UserManager {

	/**
	 * A list of all users.
	 */
	private Map<String, User> my_user_list;
	
	/**
	 * A list of all users by id.
	 */
	private Map<Integer, User> my_user_list_by_id;
	
	/**
	 * A list of Program Chairs.
	 */
	private Map<String, ProgramChair> my_program_chair_list;
	
	/**
	 * A list of Program Chairs by id.
	 */
	private Map<Integer, ProgramChair> my_program_chair_list_by_id;
	
	/**
	 * A list of Sub Program Chairs.
	 */
	private Map<String, SubProgramChair> my_sub_chair_list;
	
	/**
	 * A list of Sub Program Chairs by id.
	 */
	private Map<Integer, SubProgramChair> my_sub_chair_list_by_id;
	
	/**
	 * A list of Reviewers.
	 */
	Map<String, Reviewer> my_reviewer_list;
	
	/**
	 * A list of Reviewers by id.
	 */
	private Map<Integer, Reviewer> my_reviewer_list_by_id;
	
	/**
	 * A list of Authors. Everyone without a role is an author.
	 */
	private Map<String, Author> my_author_list;
	
	private Map<Integer, Author> my_author_list_by_id;
	
	/**
	 * The constructor of UserManager will read the <i>users</i> file in the <i>data</i> folder
	 * and generate a few lists of users.
	 */
	UserManager() {
		loadUser();
		List<Paper> papers = Paper.getAllPapers();
		List<Review> reviews = Review.getAllReviews();
		Map<Integer, Paper> paper_map = new HashMap<Integer, Paper>();
		for(Paper p : papers) {
			paper_map.put(p.getId(), p);
			my_author_list.get(p.getAuthor()).addPaper(p);
			my_sub_chair_list.get(p.getSubChair()).addPaper(p);
		}
		for(Review r : reviews) {
			paper_map.get(r.getPaperId()).addReview(r);
			my_reviewer_list_by_id.get(
					r.getUserId()).updateReview(r, 
												paper_map.get(r.getPaperId()));
		}
	}
	
	/**
	 * Private method to load users to lists.
	 */
	private void loadUser() {
		my_user_list = new HashMap<String, User>();
		my_user_list_by_id = new HashMap<Integer, User>();
		my_program_chair_list = new HashMap<String, ProgramChair>();
		my_program_chair_list_by_id = new HashMap<Integer, ProgramChair>();
		my_sub_chair_list = new HashMap<String, SubProgramChair>();
		my_sub_chair_list_by_id = new HashMap<Integer, SubProgramChair>();
		my_reviewer_list = new HashMap<String, Reviewer>();
		my_reviewer_list_by_id = new HashMap<Integer, Reviewer>();
		my_author_list = new HashMap<String, Author>();
		my_author_list_by_id = new HashMap<Integer, Author>();
		File user_data = new File("data/users.ini");
		try {
			if (!user_data.canRead()) {
				System.err.println("Error: user data not found.");
				System.err.println("Generating an empty user data.");
				user_data.createNewFile();
			}			
			Scanner input = new Scanner(user_data);
			while (input.hasNextLine()) {
				String raw_user = input.nextLine();
				String[] user_param = raw_user.replaceAll("[\"]", "").split(",");
				String user_role = user_param[user_param.length-1];
				int userID = Integer.parseInt(user_param[0]);
				String user_email = user_param[2].toLowerCase();
				String user_name = user_param[1];
				
				if (user_role.equals("Program Chair")) {
					User new_user = new ProgramChair(userID, user_email, user_name);
					my_program_chair_list.put(user_email, (ProgramChair) new_user);
					my_program_chair_list_by_id.put(userID, (ProgramChair) new_user);
					my_user_list.put(user_email, new_user);
					my_user_list_by_id.put(userID, new_user);
				} else if (user_role.equals("SubProgram Chair")) {
					User new_user = new SubProgramChair(userID, user_email, user_name);
					my_sub_chair_list.put(user_email, (SubProgramChair) new_user);
					my_sub_chair_list_by_id.put(userID, (SubProgramChair) new_user);
					my_user_list.put(user_email, new_user);
					my_user_list_by_id.put(userID, new_user);
				} else if (user_role.equals("Reviewer")) {
					User new_user = new Reviewer(userID, user_email, user_name);
					my_reviewer_list.put(user_email, (Reviewer) new_user);
					my_reviewer_list_by_id.put(userID, (Reviewer) new_user);
					my_user_list.put(user_email, new_user);
					my_user_list_by_id.put(userID, new_user);
				} else {
					User new_user = new Author(userID, user_email, user_name);
					my_author_list.put(user_email, (Author) new_user);
					my_author_list_by_id.put(userID, (Author) new_user);
					my_user_list.put(user_email, new_user);
					my_user_list_by_id.put(userID, new_user);
				}
			}
			input.close();
		} 
		catch (IOException e) {
			// An empty file will be created if the file can't be found.
			assert false;
		}
	}
	
	/**
	 * Login with the user's email address.
	 * @param email the email address of the user1
	 * @return the <code>User</code> object if the user exists, <code>null</code> if the user doesn't exist
	 */
	public User login(String email) {
		return my_user_list.get(email.toLowerCase());
	}
	
	/**
	 * Get a list of all users.
	 * @return an <code>ArrayList</code> of <code>User</code>
	 */
	public List<User> getUserList() {
		return new ArrayList<User>(my_user_list.values());
	}
	
	/**
	 * Get a user by its id.
	 * @param id the id of a user
	 * @return the user
	 */
	public User getUserByID(int id) {
		return my_user_list_by_id.get(id);
	}
	
	/**
	 * Get a list of Program Chairs.
	 * @return an <code>ArrayList</code> of <code>ProgramChair</code>
	 */
	public List<ProgramChair> getProgramChairList() {
		return new ArrayList<ProgramChair>(my_program_chair_list.values());
	}
	
	/**
	 * Get a ProgramChair by its id.
	 * @param id the id of a program chair
	 * @return the ProgramChair
	 */
	public ProgramChair getProgramChairByID(int id) {
		return my_program_chair_list_by_id.get(id);
	}
	
	/**
	 * Get a list of Sub Program Chairs.
	 * @return an <code>ArrayList</code> of <code>SubProgramChair</code>
	 */
	public List<SubProgramChair> getSubChairList() {
		return new ArrayList<SubProgramChair>(my_sub_chair_list.values());
	}
	
	/**
	 * Get a SubProgramChair by its id.
	 * @param id the id of a sub program chair
	 * @return the SubProgramChair
	 */
	public SubProgramChair getSubChairByID(int id) {
		return my_sub_chair_list_by_id.get(id);
	}
	
	/**
	 * Get a list of Reviewers.
	 * @return an <code>ArrayList</code> of <code>Reviewer</code>
	 */
	public List<Reviewer> getReviewerList() {
		return new ArrayList<Reviewer>(my_reviewer_list.values());
	}
	
	/**
	 * Get a Reviewer by its id.
	 * @param id the id of a reviewer
	 * @return the Reviewer
	 */
	public Reviewer getReviewerByID(int id) {
		return my_reviewer_list_by_id.get(id);
	}
	
	/**
	 * Get a list of Authors.
	 * @return an <code>ArrayList</code> of <code>Author</code>
	 */
	public List<Author> getAuthorList() {
		return new ArrayList<Author>(my_author_list.values());
	}
	
	/**
	 * Get a Author by its id.
	 * @param id the id of the author
	 * @return the Author
	 */
	public Author getAuthorByID(int id) {
		return my_author_list_by_id.get(id);
	}
	
	/**
	 * Test run for the UserManager
	 * @param args not used
	 */
	public static void main(String[] args) {
		UserManager m = new UserManager();
		System.out.println("User List:");
		for (User u : m.getUserList()) {
			System.out.println(u.toString() + "\t" + u.getClass().getName());
			
		}
		
	}
}
